package com.quiz.bis.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.yulichang.wrapper.JoinAbstractLambdaWrapper;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import com.quiz.bis.constant.QuestionType;
import com.quiz.bis.domain.bo.BisQuestionsSaveBo;
import com.quiz.bis.domain.bo.BisQuestionsBo;
import com.quiz.bis.domain.bo.OptionsBo;
import com.quiz.bis.domain.model.BisCategories;
import com.quiz.bis.domain.model.BisKnowPoints;
import com.quiz.bis.domain.model.BisOptions;
import com.quiz.bis.domain.model.BisQuestions;
import com.quiz.bis.domain.vo.BisQuestionsDetailVo;
import com.quiz.bis.domain.vo.BisQuestionsVo;
import com.quiz.bis.mapper.BisOptionsMapper;
import com.quiz.bis.mapper.BisQuestionsMapper;
import com.quiz.bis.service.IBisQuestionsService;
import com.quiz.common.mybatis.core.page.PageQuery;
import com.quiz.common.mybatis.core.page.TableDataInfo;
import com.quiz.common.mybatis.core.query.LambdaQueryWrapperPlus;
import com.quiz.common.mybatis.core.query.MPJLambdaWrapperPlus;
import com.quiz.common.mybatis.core.query.PlusWrappers;
import com.quiz.file.service.IFileService;
import lombok.RequiredArgsConstructor;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.safety.Safelist;
import org.jsoup.select.Elements;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;


/**
 * 题目Service业务层处理
 *
 * @author ahuan
 * @date 2025-02-22
 */
@Service
@RequiredArgsConstructor
public class BisQuestionsServiceImpl implements IBisQuestionsService {
    private final BisQuestionsMapper baseMapper;

    private final BisOptionsMapper optionsMapper;

    private final IFileService fileService;

    /**
     * 查询题目
     *
     * @param questionId 题目主键
     * @return 题目
     */
    @Override
    public BisQuestionsDetailVo selectBisQuestionsByQuestionId(Long questionId) {
        BisQuestions bisQuestions = baseMapper.selectOne(BisQuestions::getQuestionId, questionId);
        BisQuestionsDetailVo vo = BeanUtil.copyProperties(bisQuestions, BisQuestionsDetailVo.class);
        vo.setPointId(ObjUtil.isNotEmpty(bisQuestions.getPointId())?bisQuestions.getPointId().toString():null);
        if (bisQuestions.getQuestionType().equals(QuestionType.SINGLE)
                || bisQuestions.getQuestionType().equals(QuestionType.MULTIPLE)
                || bisQuestions.getQuestionType().equals(QuestionType.FILL)) {
            List<BisOptions> options = optionsMapper.selectList(BisOptions::getQuestionId, bisQuestions.getQuestionId());
            List<OptionsBo.Item> items = BeanUtil.copyToList(options, OptionsBo.Item.class);
            OptionsBo optionsBo = new OptionsBo();
            optionsBo.setType(vo.getQuestionType());
            optionsBo.setItems(items);
            vo.setOptions(optionsBo);
        }

        return vo;
    }

    /**
     * 查询题目列表
     *
     * @param bisQuestionsBo 题目
     * @return 题目
     */
    @Override
    public <T> TableDataInfo<T> selectBisQuestionsPage(BisQuestionsBo bisQuestionsBo, Class<T> voClass , PageQuery page) {
        Page<T> ts = baseMapper.selectJoinPage(page.build(), voClass, getMpjLambdaQueryWrapperPlus(bisQuestionsBo));
        //过滤掉题干中的<strong>标签
        for (T t : ts.getRecords()) {
            // 定义白名单：基于 relaxed()，添加自定义标签，移除 <strong>
            // 防止xss攻击，移除script、iframe
            Safelist safelist = Safelist.none()
                    .removeTags("strong", "script", "iframe");
            BisQuestionsVo vo = (BisQuestionsVo) t;
//            vo.setQuestionText(Jsoup.clean(vo.getQuestionText(), safelist));
            vo.setQuestionText(removeSpecificTags(vo.getQuestionText(), new String[]{"strong"}));

        }
        return TableDataInfo.build(ts);
    }



    @Override
    public <T> List<T> selectBisQuestionsList(BisQuestionsBo bisQuestions, Class<T> returnData) {
        return baseMapper.selectJoinList(returnData, getMpjLambdaQueryWrapperPlus(bisQuestions));
    }

    /**
     * 新增题目
     *
     * @param bisQuestions 题目
     * @return 结果
     */
    @SuppressWarnings("all")
    @Override
    @Transactional
    public Boolean insertBisQuestions(BisQuestionsSaveBo bo) {
        // 添加题目 包含了判断题和问答题题答案 判断题1-正确 0-错误 问答题是文件id
        BisQuestions insert = BeanUtil.copyProperties(bo, BisQuestions.class);
        insert.setCorrectAnswer(bo.getCorrectAnswer().toString());
        baseMapper.insert(insert);
        if (insert.getQuestionId() == null) {
            return false;
        }

        // 处理单选题、多选题、填空题答案选项
        List<BisOptions> options = new ArrayList<>();
        if (bo.getQuestionType().equals(QuestionType.SINGLE)
                || bo.getQuestionType().equals(QuestionType.MULTIPLE)
                || bo.getQuestionType().equals(QuestionType.FILL)) {
            List<OptionsBo.Item> items = bo.getOptions().getItems();
            items.forEach(item -> {
                BisOptions option = new BisOptions();
                BeanUtil.copyProperties(item, option);
                option.setQuestionId(insert.getQuestionId());
                option.setType(bo.getOptions().getType());
                options.add(option);
            });
        }
        if (CollUtil.isNotEmpty(options)) {
            return optionsMapper.insertBatch(options);
        }
        return true;
    }

    /**
     * 修改题目
     *
     * @param bo 题目
     * @return 结果
     */
    @Override
    @Transactional
    public int updateBisQuestions(BisQuestionsSaveBo bo) {
        // 添加题目 包含了判断题和问答题题答案 判断题1-正确 0-错误 问答题是文件id
        BisQuestions update = BeanUtil.copyProperties(bo, BisQuestions.class);
        update.setCorrectAnswer(bo.getCorrectAnswer().toString());

        int flag = 1;
        if (baseMapper.updateById(update) <= 0) {
            flag = 0;
        }

        // 处理单选题、多选题、填空题答案选项
        List<BisOptions> options = new ArrayList<>();
        if (bo.getQuestionType().equals(QuestionType.SINGLE)
                || bo.getQuestionType().equals(QuestionType.MULTIPLE)
                || bo.getQuestionType().equals(QuestionType.FILL)) {
            List<OptionsBo.Item> items = bo.getOptions().getItems();
            items.forEach(item -> {
                BisOptions option = new BisOptions();
                BeanUtil.copyProperties(item, option);
                option.setQuestionId(update.getQuestionId());
                option.setType(bo.getOptions().getType());
                options.add(option);
            });
        }
        if (CollUtil.isNotEmpty(options)) {
            if (!optionsMapper.updateBatchById(options)) {
                flag = 0;
            }
        }
        return flag;
    }

    /**
     * 批量删除题目
     *
     * @param questionIds 需要删除的题目主键
     * @return 结果
     */
    @Override
    public int deleteBisQuestionsByQuestionIds(Long[] questionIds) {
        List<Long> ids = Arrays.stream(questionIds).collect(Collectors.toList());
        List<BisQuestions> bisQuestions = baseMapper.selectBatchIds(ids);
        // 单选、多选、填空题删除选项
        bisQuestions.forEach(item -> {
            if (item.getQuestionType().equals(QuestionType.SINGLE)
                    || item.getQuestionType().equals(QuestionType.MULTIPLE)
                    || item.getQuestionType().equals(QuestionType.FILL)) {
                LambdaQueryWrapperPlus<BisOptions> wrapper = PlusWrappers.lambdaQuery(BisOptions.class)
                        .eq(BisOptions::getQuestionId, item.getQuestionId());
                optionsMapper.delete(wrapper);
            }
        });

        // 问答题需要删除附件
        bisQuestions.forEach(item -> {
            if (item.getQuestionType().equals(QuestionType.ESSAY)) {
                fileService.deleteFileByFileIds(item.getFileIds());
            }
        });

        return baseMapper.deleteBatchIds(Arrays.asList(questionIds));
    }

    /**
     * 删除题目信息
     *
     * @param questionId 题目主键
     * @return 结果
     */
    @Override
    public int deleteBisQuestionsByQuestionId(Long questionId) {
        return baseMapper.deleteById(questionId);
    }


    public MPJLambdaWrapper<BisQuestions> getMpjLambdaQueryWrapperPlus(BisQuestionsBo bisQuestionsBo) {
        return new MPJLambdaWrapperPlus<>(BisQuestions.class)
                .leftJoin(BisCategories.class, BisCategories::getCategoryId, BisQuestions::getCategoryId)
                .leftJoin(BisKnowPoints.class, BisKnowPoints::getPointId, BisQuestions::getPointId)
                .selectAll(BisQuestions.class)
                .select(BisCategories::getCategoryName)
                .selectAs(BisKnowPoints::getName, "pointName")
                .likeIfExists(BisQuestions::getQuestionTitle, bisQuestionsBo.getQuestionTitle())
                .likeIfExists(BisQuestions::getQuestionText, bisQuestionsBo.getQuestionText())
                .likeIfExists(BisQuestions::getCreateName, bisQuestionsBo.getCreateName())
                .eqIfExists(BisQuestions::getQuestionType, bisQuestionsBo.getQuestionType())
                .eqIfExists(BisQuestions::getDifficulty, bisQuestionsBo.getDifficulty())
                .eqIfExists(BisQuestions::getCategoryId, bisQuestionsBo.getCategoryId())
                .leIfExists(BisQuestions::getCreateTime, bisQuestionsBo.getEndTime())
                .geIfExists(BisQuestions::getCreateTime, bisQuestionsBo.getBeginTime())
                //禁用所有逻辑删除，同时开启主表逻辑删除
                .eq(BisQuestions::getDelFlag, 0)
                .disableLogicDel()
                .disableSubLogicDel();
    }

    public String removeSpecificTags(String html, String[] tagsToRemove) {
        // 1. 解析 HTML
        Document doc = Jsoup.parse(html);

        // 2. 遍历需要移除的标签
        for (String tag : tagsToRemove) {
            Elements elements = doc.select(tag);
            // 移除标签及其内容
            //  elements.forEach(Element::remove);
            // 仅移除标签,内容保留
            elements.unwrap();
        }

        // 3. 返回处理后的 HTML
        return doc.body().html();
    }

}

